﻿using System;
using System.Collections.Generic;
using FairyGUI;
using SimpleCore.RedDot;
using Object = UnityEngine.Object;

namespace SimpleCore
{
    public abstract partial class UIWindow : Window
    {
        /// <summary>
        /// 是否是独立界面。（这里的独立指的是唯一显示的一级界面）
        /// </summary>
        public virtual bool IsSingle { get; }

        /// <summary>
        /// 刷新界面（刷新必须传参，否则没必要刷新）
        /// </summary>
        /// <param name="arg"></param>
        public virtual void Refresh(object arg)
        {
        }

        /// <summary>
        /// 重写dispose注意调用base.Dispose(), 或者RemoveReferecePackages()。
        /// 界面销毁时，卸载当前界面所用的Package。
        /// </summary>
        public override void Dispose()
        {
            RemoveReferecePackages();
            UnloadAssets();
            
            RemoveRedDot();
            
            base.Dispose();
        }

        /// <summary>
        /// 添加当前界面所用的Package。
        /// 静态变量存储引用计数，局部变量存储当前引用的Package路径。
        /// </summary>
        /// <param name="packagePath"></param>
        protected void AddPackage(string packagePath)
        {
            if (_packageReferenceMap.TryGetValue(packagePath, out int referenceCount))
            {
                if (referenceCount == 0)
                {
                    UIPackage.AddPackage(packagePath);
                }

                _packageReferenceMap[packagePath]++;
            }
            else
            {
                _packageReferenceMap.Add(packagePath, 1);
                UIPackage.AddPackage(packagePath);
            }
            _referencePackages.Add(packagePath);
        }

        /// <summary>
        /// 移除所有当前引用的Package
        /// </summary>
        protected void RemoveReferecePackages()
        {
            for (int i = 0; i < _referencePackages.Count; i++)
            {
                string packagePath = _referencePackages[i];
                if (_packageReferenceMap.TryGetValue(packagePath, out int referenceCount))
                {
                    if (referenceCount == 1)
                    {
                        UIPackage.RemovePackage(packagePath);
                    }
                    _packageReferenceMap[packagePath]--;
                
                    if (_packageReferenceMap[packagePath] == 0)
                    {
                        _packageReferenceMap.Remove(packagePath);
                    }
                }
            }
        }

        protected T LoadAsset<T>(string path, int loaderId) where T : Object
        {
            _loadedResPathQueue.Enqueue((loaderId, path));
            return LoadTool.Load<T>(path, loaderId);
        }

        protected void UnloadAssets()
        {
            while (_loadedResPathQueue.Count>0)
            {
                var loadData = _loadedResPathQueue.Dequeue();
                LoadTool.Unload(loadData.Item2, loadData.Item1);
            }
        }

        /// <summary>
        /// 添加指定obj为T类型的红点，一个obj可以重复添加；
        /// 添加的红点，界面销毁时自动取消添加；
        /// 有重复添加过滤判定；
        /// </summary>
        /// <param name="obj">指定obj</param>
        /// <typeparam name="T">红点条件检测器类型</typeparam>
        protected void AddRedDot<T>(GObject obj) where T : RedDotConditionChecker, new()
        {
            //不在初始化时创建，避免没有使用红点系统时，始终存在一个无用的对象
            if (_redDotManager == null)
            {
                _redDotManager = new RedDotManager();
            }

            if (_redDotManager.AddRedDot<T>(obj))
            {
                _redDotObjsQueue.Enqueue(obj);
            }
        }

        void RemoveRedDot()
        {
            while (_redDotObjsQueue.Count > 0)
            {
                _redDotManager.RemoveRedDotAll(_redDotObjsQueue.Dequeue());
            }
        }

        //加载资源相关
        private Queue<(int, string)> _loadedResPathQueue = new Queue<(int, string)>();
        List<string> _referencePackages = new List<string>();
        private static Dictionary<string, int> _packageReferenceMap = new Dictionary<string, int>();

        //红点相关
        Queue<GObject> _redDotObjsQueue = new Queue<GObject>();
        private static RedDotManager _redDotManager;
    }

    /// <summary>
    /// 继承于UIWindow，使用泛型，避免写Window界面时需要手动转界面GComp类型
    /// </summary>
    /// <typeparam name="T">当前界面的界面组件</typeparam>
    public abstract class UIWindow<T> : UIWindow where T : GComponent
    {
        /// <summary>
        /// 当前界面的界面组件
        /// </summary>
        protected T Comp;
    }
}